﻿#pragma once

//void my_memcpy(void* dst, const void* src, size_t&& size) {
//	char* d = (char*)dst;
//	const char* s = (const char*)src;
//	for (size_t i = 0; i < size; ++i)
//		/*((char*)dst)[i] = ((char*)src)[i]; */  // 每次都类型转换，浪费算力
//		d[i] = s[i]; // 只需要一次类型转换
//}

namespace my_auto_ptr {
	/*
	本命名空间基本完全实现标准库智能指针中的 unique_ptr、shared_ptr 和 weak_ptr 常用基本功能，建议先听完 Chenno 大佬老师的  C++ 课程前 92 集讲解后再回头食用！
	*/
	template<typename Ty>
	class UniquePtr {
	private:
		Ty* ptr;

	public:
		UniquePtr() : ptr(nullptr) {} // 禁止默认构造函数
		UniquePtr(const UniquePtr& other) = delete; // 拷贝构造函数
		UniquePtr& operator=(const UniquePtr& other) = delete; // 拷贝赋值运算符
		UniquePtr& operator=(UniquePtr&& other) {
			ptr = other.ptr;
			other.ptr = nullptr;
			return *this;
		} // 移动赋值运算符
		UniquePtr(UniquePtr&& other) noexcept // 移动构造函数
			: ptr(other.ptr) {
			other.ptr = nullptr;
		}
		UniquePtr(Ty* p = nullptr)
			:ptr(p) {
		} // 构造函数

		~UniquePtr() {	// 析构函数
			if (ptr) {
				ptr->~Ty(); // 调用Ty的析构函数
				ptr = nullptr;
			}
		}

		Ty* operator->() { // 取指针运算符
			return ptr;
		}

		const Ty* operator->() const { // 取常指针运算符
			return ptr;
		}

		Ty& operator*() const { // 取值运算符
			return *ptr;
		}

		Ty* get() const { // 获取指针
			return ptr;
		}
	};

	template<typename Ty>
	Ty* MakeUnique(Ty*&& ptr = new Ty()) { // 右值引用
		UniquePtr<Ty> upr(ptr);
		return std::move(upr.get()); // 转移资源所有权
	}

	template<typename Ty>
	class BasePtr {
	protected:
		Ty* ptr = nullptr;
		size_t* base_share_count = nullptr;
		size_t* my_weak_count = nullptr;

	public:
		BasePtr() {} // 默认构造函数
		~BasePtr() {} // 析构函数

		void set_ptr(const Ty* p) {
			ptr = const_cast<Ty*>(p);
		}

		Ty* get_ptr() const { // 获取指针
			return ptr;
		}

		const size_t* get_shared_count() const { // 获取引用计数
			return base_share_count;
		}

		const size_t* get_weak_count() const { // 获取弱引用计数
			return my_weak_count;
		}
	};

	template<typename Ty>
	class SharedPtr : protected BasePtr<Ty> {
	private:
		Ty* shared_ptr = nullptr;
		size_t* share_count = nullptr;

	public:
		constexpr SharedPtr() noexcept {
			if (!share_count) {
				share_count = new size_t(1);
				this->base_share_count = share_count;
			}
		}; // 默认构造函数
		SharedPtr(Ty*&& p) {
			this->ptr = shared_ptr = p;
			if (!share_count) {
				share_count = new size_t(1);
				this->base_share_count = share_count;
			}
			else {
				++*share_count;
				this->base_share_count = share_count;
			}
		} // 构造函数
		SharedPtr(const SharedPtr& other) {
			if (share_count && (*share_count > 1))
				--*share_count; // 发生转移，减少引用计数
			else if (!share_count || (*share_count <= 1))
				this->~SharedPtr(); // 原来只有一个引用，现在有多个引用，需要释放原来的资源
			this->ptr = other.ptr;
			shared_ptr = other.shared_ptr;
			share_count = other.share_count;
			if (share_count)
				++*share_count;
			this->base_share_count = share_count;
		} // 拷贝构造函数
		SharedPtr& operator=(SharedPtr& other) {
			if (share_count && (*share_count > 1))
				--*share_count; // 发生转移，减少引用计数
			else if (!share_count || (*share_count <= 1))
				this->~SharedPtr(); // 原来只有一个引用，现在有多个引用，需要释放原来的资源
			this->ptr = other.ptr;
			shared_ptr = other.shared_ptr;
			share_count = other.share_count;
			if (share_count)
				++*share_count;
			this->base_share_count = share_count;
			return *this;
		} // 拷贝赋值运算符

		~SharedPtr() { // 析构函数
			if (!share_count || (*share_count == 1)) { // 只有 0/1 个引用，释放资源
				if (share_count && (*share_count == 1))
					--*share_count; // 保证引用计数正确
				shared_ptr->~Ty(); // 调用Ty的析构函数
				delete shared_ptr;
				shared_ptr = nullptr;
				share_count = nullptr;
			}
			else if (share_count)
				--*share_count;
		}

		Ty* operator->() { // 取指针运算符
			return shared_ptr;
		}
		const Ty* operator->() const { // 取常指针运算符
			return shared_ptr;
		}
		Ty& operator*() const { // 取值运算符
			return *shared_ptr;
		}
		const size_t* use_count() const { // 获取引用计数，用于判断是否已经过期
			return share_count;
		}
		const Ty* get_shared_ptr() const { // 获取指针
			return shared_ptr;
		}
		constexpr size_t* get_weak_count() const noexcept { // 获取弱引用计数
			return this->my_weak_count;
		}
	};

	template<typename Ty>
	Ty* MakeShared(Ty*&& ptr = new Ty()) { // 右值引用
		//SharedPtr<Ty> spr(ptr);
		//return const_cast<Ty*>(std::move(spr.get_shared_ptr())); // 转移资源所有权
		return ptr;
	}

	template<typename Ty> // 注意模版类继承的写法
	class WeakPtr : public BasePtr<Ty> { // 弱引用，不增加共享引用计数，继承 SharedPtr
	public:
		constexpr WeakPtr() noexcept {
			if (!this->my_weak_count) { this->my_weak_count = new size_t(1); }; // 默认构造函数
		}; // 默认构造函数

		~WeakPtr() {
			if (!this->my_weak_count || (*this->my_weak_count == 1)) {
				if (this->my_weak_count && (*this->my_weak_count == 1))
					--*this->my_weak_count; // 保证引用计数正确
				delete this->my_weak_count;
				this->my_weak_count = nullptr;
			}
			else
				-- * this->my_weak_count;
		} // 析构函数，会自动调用父类的析构函数

		WeakPtr(const WeakPtr& other) noexcept {
			if (!this->my_weak_count || *this->my_weak_count == 1 || *this->my_weak_count == 0)
				this->~WeakPtr(); // 原来只有零个、一个弱引用，现在有多个弱引用，需要释放原来的资源
			else
				-- * this->my_weak_count;
			this->my_weak_count = const_cast<size_t*>(other.get_weak_count());
			if (this->my_weak_count)
				++*this->my_weak_count;
			this->ptr = const_cast<Ty*>(other.get_ptr());
		}

		WeakPtr& operator=(const WeakPtr& other) noexcept {
			if (!this->my_weak_count || *this->my_weak_count == 1 || *this->my_weak_count == 0)
				this->~WeakPtr(); // 原来只有零个、一个弱引用，现在有多个弱引用，需要释放原来的资源
			else
				-- * this->my_weak_count;
			this->my_weak_count = const_cast<size_t*>(other.get_weak_count());
			if (this->my_weak_count)
				++*this->my_weak_count;
			this->ptr = const_cast<Ty*>(other.get_ptr());
			return *this;
		}

		WeakPtr(const SharedPtr<Ty>& other) noexcept {
			if (this->my_weak_count && (*this->my_weak_count > 0))
				--*this->my_weak_count; // 发生转移，减少弱引用计数
			if (other.get_weak_count()) {
				this->my_weak_count = const_cast<size_t*>(other.get_weak_count());
				++*this->my_weak_count;
			}
			else if (other.get_shared_ptr() &&
				(!this->my_weak_count || !*this->my_weak_count)) {
				this->my_weak_count = new size_t(1);// 原来没弱引用，现在有弱引用，需要新建弱引用计数
				size_t*&& p = const_cast<size_t*>(other.get_weak_count());
				p = this->my_weak_count; // 右值转左值
			}
			if (this->get_ptr() != other.get_shared_ptr())
				this->set_ptr(other.get_shared_ptr()); // 原来没有资源或现在有新资源，更新指针
			this->base_share_count = const_cast<size_t*>(other.use_count());
		} // 构造函数，从 SharedPtr 构造 WeakPtr

		WeakPtr operator=(const SharedPtr<Ty>& other) noexcept { // 拷贝赋值运算符
			if (this->my_weak_count && (*this->my_weak_count > 0))
				--*this->my_weak_count; // 发生转移，减少弱引用计数
			if (other.get_weak_count()) {
				this->my_weak_count = const_cast<size_t*>(other.get_weak_count());
				++*this->my_weak_count;
			}
			else if (other.get_shared_ptr() &&
				(!this->my_weak_count || !*this->my_weak_count)) {
				this->my_weak_count = new size_t(1);// 原来没弱引用，现在有弱引用，需要新建弱引用计数
				size_t*&& p = const_cast<size_t*>(other.get_weak_count());
				p = this->my_weak_count; // 右值转左值
			}
			if (this->get_ptr() != other.get_shared_ptr())
				this->set_ptr(other.get_shared_ptr()); // 原来没有资源或现在有新资源，更新指针
			this->base_share_count = const_cast<size_t*>(other.use_count());
			return *this;
		}

		bool expired() const { // 是否已经过期
			return this->base_share_count == 0;
		}

		void reset() {
			if (this->my_weak_count && *this->my_weak_count > 0)
				--*this->my_weak_count;
			this->ptr = nullptr;
			this->base_share_count = nullptr;
			this->my_weak_count = nullptr;
		}

		Ty* lock() const { // 尝试获取资源，如果已经过期，则返回 nullptr
			return this->get_ptr();
		}
	};
}